﻿using System.IO;
using System.Text;
using KSS.Generator.Configuration;
using KSS.Generator.Schema;

namespace KSS.Generator
{
    public class EntityProjectGenerator : ProjectGenerator
    {
        public override string ProjectName
        {
            get { return Template.Project.EntityProjectName; }
        }

        protected override void GenerateFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            switch (templateFile.Name)
            {
                case Template.EntityProject.GeneratedEntityFileName:
                    GenerateEntityFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.EntityProject.CustomEntityFileName:
                    GenerateCustomEntityFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.EntityProject.GeneratedStoreResultFileName:
                    GenerateStoreResultFile(projectConfig, templateFile, generatedDirectory);
                    break;

                case Template.EntityProject.CustomStoreResultFileName:
                    GenerateCustomStoreResultFile(projectConfig, templateFile, generatedDirectory);
                    break;
            }
        }

        private void GenerateEntityFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Table t in Context.DatabaseSchema.Tables)
            {
                #region { Entity custom tag }

                // find entity name property
                projectConfig.SetPropertyValue(Template.EntityProject.CustomTag_EntityName, t.DataType.Name);
                #endregion

                #region { Declaration property tag }

                StringBuilder sbPropertyDeclaration = new StringBuilder();

                // create property declaration
                foreach (Column c in t.DataType.Columns)
                {
                    // variable declaration
                    sbPropertyDeclaration.AppendFormat(
                                Template.EntityProject.Variable,
                                GeneratorHelper.GeneratePrivateVariableName(c.Name),
                                GeneratorHelper.GetTypeFromColumn(c));

                    // property declaration
                    string propertyDeclaration = string.Format(
                                Template.EntityProject.Property,
                                c.Name,
                                GeneratorHelper.GetTypeFromColumn(c),
                                GeneratorHelper.GeneratePrivateVariableName(c.Name));

                    // fill barrack character
                    propertyDeclaration = propertyDeclaration.Replace("(", "{");
                    propertyDeclaration = propertyDeclaration.Replace(")", "}");
                    sbPropertyDeclaration.Append(propertyDeclaration);

                    sbPropertyDeclaration.AppendLine();
                }

                // Find declaration property
                projectConfig.SetPropertyValue(
                            Template.EntityProject.CustomTag_PropertyDeclaration,
                            sbPropertyDeclaration.ToString());
                #endregion

                // Fill property in template
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write to source file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, t.DataType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        private void GenerateCustomEntityFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Table t in Context.DatabaseSchema.Tables)
            {
                #region { Entity custom tag }

                // find entity name property
                projectConfig.SetPropertyValue(Template.EntityProject.CustomTag_EntityName, t.DataType.Name);
                #endregion

                // Fill property in template
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write to source file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, t.DataType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode, true);
            }
        }

        private void GenerateStoreResultFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Function f in Context.DatabaseSchema.Functions)
            {
                if (f.ElementType == null ||
                    string.IsNullOrEmpty(f.ElementType.Name))
                {
                    continue;
                }

                #region { Entity custom tag }

                // find entity name property
                projectConfig.SetPropertyValue(Template.EntityProject.CustomTag_EntityName, f.ElementType.Name);
                #endregion

                #region { Declaration property tag }

                StringBuilder sbPropertyDeclaration = new StringBuilder();

                // create property declaration
                foreach (Column c in f.ElementType.Columns)
                {
                    // variable declaration
                    sbPropertyDeclaration.AppendFormat(
                                Template.EntityProject.Variable,
                                GeneratorHelper.GeneratePrivateVariableName(c.Name),
                                GeneratorHelper.GetTypeFromColumn(c));

                    // property declaration
                    string propertyDeclaration = string.Format(
                                Template.EntityProject.Property,
                                c.Name,
                                GeneratorHelper.GetTypeFromColumn(c),
                                GeneratorHelper.GeneratePrivateVariableName(c.Name));

                    // fill barrack character
                    propertyDeclaration = propertyDeclaration.Replace("(", "{");
                    propertyDeclaration = propertyDeclaration.Replace(")", "}");
                    sbPropertyDeclaration.Append(propertyDeclaration);

                    sbPropertyDeclaration.AppendLine();
                }

                // Find declaration property
                projectConfig.SetPropertyValue(
                            Template.EntityProject.CustomTag_PropertyDeclaration,
                            sbPropertyDeclaration.ToString());
                #endregion

                // Fill property in template
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write to source file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, f.ElementType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }

        private void GenerateCustomStoreResultFile(ProjectSetting projectConfig, FileInfo templateFile, DirectoryInfo generatedDirectory)
        {
            string templateContent = GeneratorHelper.ReadFromFile(templateFile.FullName);
            string fileNameFormat = GeneratorHelper.GetFileNameFromat(templateFile.Name);

            // Fill methods to template
            foreach (Function f in Context.DatabaseSchema.Functions)
            {
                if (f.ElementType == null ||
                    string.IsNullOrEmpty(f.ElementType.Name))
                {
                    continue;
                }

                #region { Entity custom tag }

                // find entity name property
                projectConfig.SetPropertyValue(Template.EntityProject.CustomTag_EntityName, f.ElementType.Name);
                #endregion

                // Fill property in template
                string sourceCode = GeneratorHelper.FillProperties(projectConfig, templateContent);

                // Write to source file
                string generatedFilePath = string.Format("{0}\\{1}",
                            generatedDirectory.FullName,
                            string.Format(fileNameFormat, f.ElementType.Name));

                GeneratorHelper.WriteToFile(generatedFilePath, sourceCode);
            }
        }
    }
}
